﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace RaptorEngine.Debugs
{
    /// <summary>
    /// Add debug class to main game, set wanted values, add to update and draw.
    /// Press F9 to toggle music.
    /// Press F10 to toggle bounding volumes.
    /// Press F11 to toggle debug data.
    /// Press F12 to toggle debug camera.
    /// </summary>
    public class Debug
    {
#if DEBUG
        private SpriteFont _debugFont;
        //Frame counter variables
        private int frameRate = 0;
        private int frameCounter = 0;
        TimeSpan elapsedTime = TimeSpan.Zero;
#endif
        public bool DrawBoundingVolumes { get; set; }

        //Camera variables
        public DebugCamera DebugCamera { get; private set; }
        public bool UseDebugCam { get; set; }

        public bool ShowDebugData { get; set; }

#if DEBUG
        private Dictionary<string, string> _debugData = new Dictionary<string, string>();
#endif
        internal Debug()
        {
#if DEBUG
            //Create debug cam
            DebugCamera = new DebugCamera(Vector3.Zero, 0, 0);
            DebugCamera.Id = Camera.DEBUG_CAM;
            GameEngine.Instance.Render.AddNewData(DebugCamera);
            ShowDebugData = true;
#endif
        }

        internal void LoadContent(SpriteFont debugFont)
        {
#if DEBUG
            _debugFont = debugFont;
#endif
        }

        internal void Update(GameTime gameTime)
        {
#if DEBUG
            if (GameEngine.Instance.Input.IsPressed(Keys.F12))
                UseDebugCam = !UseDebugCam;
            if (GameEngine.Instance.Input.IsPressed(Keys.F11))
                ShowDebugData = !ShowDebugData;
            if (GameEngine.Instance.Input.IsPressed(Keys.F10))
                DrawBoundingVolumes = !DrawBoundingVolumes;

            if (GameEngine.Instance.Input.IsPressed(Keys.F9))
            {
                if (!GameEngine.Instance.Audio.SongPaused)
                    GameEngine.Instance.Audio.PauseMusic();
                else
                    GameEngine.Instance.Audio.ResumeMusic();
            }

            if (UseDebugCam)
            {
                DebugCamera.ProcessInput(gameTime.ElapsedGameTime.Milliseconds);
            }
#endif
        }

        internal void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
#if DEBUG
            CalculateFPS(gameTime);
            SetData("fps", "" + frameRate);
            SetData("BoundingVolumes", "Visible = " + DrawBoundingVolumes);

            string data = "";
            lock (_debugData)
            {
                foreach (KeyValuePair<string, string> pair in _debugData)
                {
                    data += pair.Key + ":" + pair.Value + "\n";
                }
            }
            spriteBatch.DrawString(_debugFont, data, new Vector2(33, 33), Color.Black);
            spriteBatch.DrawString(_debugFont, data, new Vector2(32, 32), Color.White);
#endif
        }
#if DEBUG
        private void CalculateFPS(GameTime gameTime)
        {
            frameCounter++;
            elapsedTime += gameTime.ElapsedGameTime;

            if (elapsedTime > TimeSpan.FromSeconds(1))
            {
                elapsedTime -= TimeSpan.FromSeconds(1);
                frameRate = frameCounter;
                frameCounter = 0;
            }
        }
#endif
        /// <summary>
        ///  Prints data on the screen in the form "name:data" for each unique name.
        /// </summary>
        public void SetData(string name, string data)
        {
#if DEBUG
            lock (_debugData)
            {
                _debugData[name] = data;
            }
#endif
        }

        /// <summary>
        ///  Removes the debug data-line associated with "name"
        /// </summary>
        public void RemoveData(string name)
        {
#if DEBUG
            lock (_debugData)
            {
                _debugData.Remove(name);
            }
#endif
        }

        /// <summary>
        ///  Clears all debug data
        /// </summary>
        public void ClearData()
        {
#if DEBUG
            lock (_debugData)
            {
                _debugData.Clear();
            }
#endif
        }
    }
}
